package demogeneric;

/**
 * 写一个类，在类中定义一个数组，此数组可以存放任何类型的数据
 */
//class MyArray {
//    public Object[] array = new Object[3];
//
//    public void setArray(int pos, Object val) {
//        array[pos] = val;
//    }
//
//    public Object getVal(int pos) {
//        return array[pos];
//    }
//}
/**
 * 出现问题：
 * 1.太乱了，array数组里大杂烩，什么类型的数据都可以放；
 * 2.理解错误，不是数组里什么类型的数据都可以放，而是可以指定该数组放任何类型的数据；
 * 3.由此引入“泛型”——可以传递类型。
 */

/**
 * 泛型类
 * 1. <T> 为占位符，表示当前类是一个泛型类
 * 2. 泛型类型在引用时，只能是引用类型，不能是简单类型，即 <>内一定是引用类型
 * 3. 在编译时，没有泛型的概念——JVM中不存在泛型
 * 4. 泛型是如何编译的：擦除机制——T在编译后被替换成了Object
 * @param <T>
 */
class MyArray<T /*extends Number*/> {//1  //泛型的上界——T必须是Number的子类
    public Object[] array = new Object[3];

    public void setArray(int pos, T val) {//2
        array[pos] = val;
    }

    public T getVal(int pos) {//3
        return (T)array[pos];//4
    }
}

public class Test {
    public static void main(String[] args) {
        MyArray<Integer> myArray1 = new MyArray<Integer>();//5
        myArray1.setArray(0, 10);//在编译时，自动进行类型检查
        //myArray1.setArray(1, "bamboo");//err myArray1数组已指定存放整型数据
        Integer val = myArray1.getVal(0);//在编译时，自动进行类型转换
        System.out.println(val);

        MyArray<String> myArray2 = new MyArray<>();//后一个<>里面的内容可省略，编译器会进行推导，此处指定数组存放String类型的值
        myArray2.setArray(0, "haha");
        myArray2.setArray(1, "hehe");
        String ret = myArray2.getVal(0);
        System.out.println(ret);//这就是泛型，指定什么类型就可以往里面放什么类型
    }



    public static void main1(String[] args) {
        MyArray myArray = new MyArray();

        myArray.setArray(0, 10);
        myArray.setArray(1, "world");

        String ret = (String)myArray.getVal(1);//需要强转
    }
}